/******************************************************
*  Copyright(c) pages.ilovezxl.top
*  FileName :threadasync.c
*  Author : rivulet.dave
*  Description : 线程同步接口
*  Data : 2019-04-23
******************************************************/

/*********************************************************************
 * INCLUDES
 */

#include "stdrope.h"
#include "sallib.h"
#include "salagent.h"

#include "threadasync.h"

#if (SAL_PRODUCER == _SAL_LINUX_)
#include "threadasync_linux.h"
#endif

/*********************************************************************
 *  EXTERNAL VARIABLES
 */

/*********************************************************************
 * MACROS
 */

/*********************************************************************
 * TYPES
 */


/*********************************************************************
 * FUNCTIONS DECLARE
 */


/*********************************************************************
 *  VARIABLES
 */

static OS_THREADASYNC_BASE_S *s_pstThreadAsyncObject = NULL;

/*********************************************************************
 * FUNCTIONS
 */

/**
 *   @Description: 线程同步模块安装
 *   @param : NA
 *   @return: _OK/_ERR
 */
int32_t osThreadAsyncInstall(void)
{
#if (SAL_PRODUCER == _SAL_LINUX_)
    s_pstThreadAsyncObject = osThreadAsyncLinuxObjNew();
#endif
    return _OK;
}

/**
 *   @Description: 线程同步模块卸载
 *   @param : NA
 *   @return: _OK/_ERR
 */
int32_t osThreadAsyncUninstall(void)
{
    s_pstThreadAsyncObject = NULL;
    return _OK;
}

//  ==== Thread Flags Functions ====

/// Set the specified Thread Flags of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \param[in]     flags         specifies the flags of the thread that shall be set.
/// \return thread flags after setting or error code if highest bit set.
uint32_t osThreadFlagsSet (osThreadId_t thread_id, uint32_t flags)
{
    if (!s_pstThreadAsyncObject)
    {
        return 0;
    }

    if (!s_pstThreadAsyncObject->pfOSThreadFlagsSet)
    {
        return 0;
    }

    return s_pstThreadAsyncObject->pfOSThreadFlagsSet(thread_id, flags);
}
 
/// Clear the specified Thread Flags of current running thread.
/// \param[in]     flags         specifies the flags of the thread that shall be cleared.
/// \return thread flags before clearing or error code if highest bit set.
uint32_t osThreadFlagsClear (uint32_t flags)
{
    if (!s_pstThreadAsyncObject)
    {
        return 0;
    }

    if (!s_pstThreadAsyncObject->pfOSThreadFlagsClear)
    {
        return 0;
    }

    return s_pstThreadAsyncObject->pfOSThreadFlagsClear(flags);
}

/// Get the current Thread Flags of current running thread.
/// \return current thread flags.
uint32_t osThreadFlagsGet (void)
{
    if (!s_pstThreadAsyncObject)
    {
        return 0;
    }

    if (!s_pstThreadAsyncObject->pfOSThreadFlagsGet)
    {
        return 0;
    }

    return s_pstThreadAsyncObject->pfOSThreadFlagsGet();
}

/// Wait for one or more Thread Flags of the current running thread to become signaled.
/// \param[in]     flags         specifies the flags to wait for.
/// \param[in]     options       specifies flags options (osFlagsXxxx).
/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return thread flags before clearing or error code if highest bit set.
uint32_t osThreadFlagsWait (uint32_t flags, uint32_t options, uint32_t timeout)
{
    if (!s_pstThreadAsyncObject)
    {
        return 0;
    }

    if (!s_pstThreadAsyncObject->pfOSThreadFlagsWait)
    {
        return 0;
    }

    return s_pstThreadAsyncObject->pfOSThreadFlagsWait(flags, options, timeout);
}

//  ==== Event Flags Management Functions ====

/// Create and Initialize an Event Flags object.
/// \param[in]     attr          event flags attributes; NULL: default values.
/// \return event flags ID for reference by other functions or NULL in case of error.
osEventFlagsId_t osEventFlagsNew (const osEventFlagsAttr_t *attr)
{
    if (!s_pstThreadAsyncObject)
    {
        return (osEventFlagsId_t)NULL;
    }

    if (!s_pstThreadAsyncObject->pfOSEventFlagsNew)
    {
        return (osEventFlagsId_t)NULL;
    }

    return s_pstThreadAsyncObject->pfOSEventFlagsNew(attr);
}

/// Get name of an Event Flags object.
/// \param[in]     ef_id         event flags ID obtained by \ref osEventFlagsNew.
/// \return name as null-terminated string.
const char *osEventFlagsGetName (osEventFlagsId_t ef_id)
{
    if (!s_pstThreadAsyncObject)
    {
        return "no define";
    }

    if (!s_pstThreadAsyncObject->pfOSEventFlagsGetName)
    {
        return "unknow";
    }

    return s_pstThreadAsyncObject->pfOSEventFlagsGetName(ef_id);
}

/// Set the specified Event Flags.
/// \param[in]     ef_id         event flags ID obtained by \ref osEventFlagsNew.
/// \param[in]     flags         specifies the flags that shall be set.
/// \return event flags after setting or error code if highest bit set.
uint32_t osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags)
{
    if (!s_pstThreadAsyncObject)
    {
        return 0;
    }

    if (!s_pstThreadAsyncObject->pfOSEventFlagsSet)
    {
        return 0;
    }

    return s_pstThreadAsyncObject->pfOSEventFlagsSet(ef_id, flags);
}

/// Clear the specified Event Flags.
/// \param[in]     ef_id         event flags ID obtained by \ref osEventFlagsNew.
/// \param[in]     flags         specifies the flags that shall be cleared.
/// \return event flags before clearing or error code if highest bit set.
uint32_t osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags)
{
    if (!s_pstThreadAsyncObject)
    {
        return 0;
    }

    if (!s_pstThreadAsyncObject->pfOSEventFlagsClear)
    {
        return 0;
    }

    return s_pstThreadAsyncObject->pfOSEventFlagsClear(ef_id, flags);
}

/// Get the current Event Flags.
/// \param[in]     ef_id         event flags ID obtained by \ref osEventFlagsNew.
/// \return current event flags.
uint32_t osEventFlagsGet (osEventFlagsId_t ef_id)
{
    if (!s_pstThreadAsyncObject)
    {
        return 0;
    }

    if (!s_pstThreadAsyncObject->pfOSEventFlagsGet)
    {
        return 0;
    }

    return s_pstThreadAsyncObject->pfOSEventFlagsGet(ef_id);
}

/// Wait for one or more Event Flags to become signaled.
/// \param[in]     ef_id         event flags ID obtained by \ref osEventFlagsNew.
/// \param[in]     flags         specifies the flags to wait for.
/// \param[in]     options       specifies flags options (osFlagsXxxx).
/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return event flags before clearing or error code if highest bit set.
uint32_t osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout)
{
    if (!s_pstThreadAsyncObject)
    {
        return 0;
    }

    if (!s_pstThreadAsyncObject->pfOSEventFlagsWait)
    {
        return 0;
    }

    return s_pstThreadAsyncObject->pfOSEventFlagsWait(ef_id, flags, options, timeout);
}

/// Delete an Event Flags object.
/// \param[in]     ef_id         event flags ID obtained by \ref osEventFlagsNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osEventFlagsDelete (osEventFlagsId_t ef_id)
{
    if (!s_pstThreadAsyncObject)
    {
        return osError;
    }

    if (s_pstThreadAsyncObject->pfOSEventFlagsDelete)
    {
        return osOK;
    }

    return s_pstThreadAsyncObject->pfOSEventFlagsDelete(ef_id);
}


//  ==== Mutex Management Functions ====

/// Create and Initialize a Mutex object.
/// \param[in]     attr          mutex attributes; NULL: default values.
/// \return mutex ID for reference by other functions or NULL in case of error.
osMutexId_t osMutexNew (const osMutexAttr_t *attr)
{
    if (!s_pstThreadAsyncObject)
    {
        return (osMutexId_t)NULL;
    }

    if (!s_pstThreadAsyncObject->pfOSMutexNew)
    {
        return (osMutexId_t)NULL;
    }

    return s_pstThreadAsyncObject->pfOSMutexNew(attr);
}

/// Get name of a Mutex object.
/// \param[in]     mutex_id      mutex ID obtained by \ref osMutexNew.
/// \return name as null-terminated string.
const char *osMutexGetName (osMutexId_t mutex_id)
{
    if (!s_pstThreadAsyncObject)
    {
        return "no define";
    }

    if (!s_pstThreadAsyncObject->pfOSMutexGetName)
    {
        return "unknow";
    }

    return s_pstThreadAsyncObject->pfOSMutexGetName(mutex_id);
}

/// Acquire a Mutex or timeout if it is locked.
/// \param[in]     mutex_id      mutex ID obtained by \ref osMutexNew.
/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout)
{
    if (!s_pstThreadAsyncObject)
    {
        return osError;
    }

    if (!s_pstThreadAsyncObject->pfOSMutexAcquire)
    {
        return osOK;
    }

    return s_pstThreadAsyncObject->pfOSMutexAcquire(mutex_id, timeout);
}

/// Release a Mutex that was acquired by \ref osMutexAcquire.
/// \param[in]     mutex_id      mutex ID obtained by \ref osMutexNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMutexRelease (osMutexId_t mutex_id)
{
    if (!s_pstThreadAsyncObject)
    {
        return osError;
    }

    if (!s_pstThreadAsyncObject->pfOSMutexRelease)
    {
        return osOK;
    }

    return s_pstThreadAsyncObject->pfOSMutexRelease(mutex_id);
}

/// Get Thread which owns a Mutex object.
/// \param[in]     mutex_id      mutex ID obtained by \ref osMutexNew.
/// \return thread ID of owner thread or NULL when mutex was not acquired.
osThreadId_t osMutexGetOwner (osMutexId_t mutex_id)
{
    if (!s_pstThreadAsyncObject)
    {
        return (osThreadId_t)NULL;
    }

    if (!s_pstThreadAsyncObject->pfOSMutexGetOwner)
    {
        return (osThreadId_t)NULL;
    }

    return s_pstThreadAsyncObject->pfOSMutexGetOwner(mutex_id);
}

/// Delete a Mutex object.
/// \param[in]     mutex_id      mutex ID obtained by \ref osMutexNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMutexDelete (osMutexId_t mutex_id)
{
    if (!s_pstThreadAsyncObject)
    {
        return osError;
    }

    if (!s_pstThreadAsyncObject->pfOSMutexDelete)
    {
        return osOK;
    }

    return s_pstThreadAsyncObject->pfOSMutexDelete(mutex_id);
}


//  ==== Semaphore Management Functions ====

/// Create and Initialize a Semaphore object.
/// \param[in]     max_count     maximum number of available tokens.
/// \param[in]     initial_count initial number of available tokens.
/// \param[in]     attr          semaphore attributes; NULL: default values.
/// \return semaphore ID for reference by other functions or NULL in case of error.
osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr)
{
    if (!s_pstThreadAsyncObject)
    {
        return (osSemaphoreId_t)NULL;
    }

    if (!s_pstThreadAsyncObject->pfOSSemaphoreNew)
    {
        return (osSemaphoreId_t)NULL;
    }

    return s_pstThreadAsyncObject->pfOSSemaphoreNew(max_count, initial_count, attr);
}

/// Get name of a Semaphore object.
/// \param[in]     semaphore_id  semaphore ID obtained by \ref osSemaphoreNew.
/// \return name as null-terminated string.
const char *osSemaphoreGetName (osSemaphoreId_t semaphore_id)
{
    if (!s_pstThreadAsyncObject)
    {
        return "no define";
    }

    if (!s_pstThreadAsyncObject->pfOSSemaphoreGetName)
    {
        return "unknow";
    }

    return s_pstThreadAsyncObject->pfOSSemaphoreGetName(semaphore_id);
}

/// Acquire a Semaphore token or timeout if no tokens are available.
/// \param[in]     semaphore_id  semaphore ID obtained by \ref osSemaphoreNew.
/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout)
{
    if (!s_pstThreadAsyncObject)
    {
        return osError;
    }

    if (!s_pstThreadAsyncObject->pfOSSemaphoreAcquire)
    {
        return osOK;
    }

    return s_pstThreadAsyncObject->pfOSSemaphoreAcquire(semaphore_id, timeout);
}

/// Release a Semaphore token up to the initial maximum count.
/// \param[in]     semaphore_id  semaphore ID obtained by \ref osSemaphoreNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id)
{
    if (!s_pstThreadAsyncObject)
    {
        return osError;
    }

    if (!s_pstThreadAsyncObject->pfOSSemaphoreRelease)
    {
        return osOK;
    }

    return s_pstThreadAsyncObject->pfOSSemaphoreRelease(semaphore_id);
}

/// Get current Semaphore token count.
/// \param[in]     semaphore_id  semaphore ID obtained by \ref osSemaphoreNew.
/// \return number of tokens available.
uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id)
{
    if (!s_pstThreadAsyncObject)
    {
        return 0;
    }

    if (!s_pstThreadAsyncObject->pfOSSemaphoreGetCount)
    {
        return 0;
    }

    return s_pstThreadAsyncObject->pfOSSemaphoreGetCount(semaphore_id);
}

/// Delete a Semaphore object.
/// \param[in]     semaphore_id  semaphore ID obtained by \ref osSemaphoreNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id)
{
    if (!s_pstThreadAsyncObject)
    {
        return osError;
    }

    if (!s_pstThreadAsyncObject->pfOSSemaphoreDelete)
    {
        return osOK;
    }

    return s_pstThreadAsyncObject->pfOSSemaphoreDelete(semaphore_id);
}


//  ==== Message Queue Management Functions ====

/// Create and Initialize a Message Queue object.
/// \param[in]     msg_count     maximum number of messages in queue.
/// \param[in]     msg_size      maximum message size in bytes.
/// \param[in]     attr          message queue attributes; NULL: default values.
/// \return message queue ID for reference by other functions or NULL in case of error.
osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr)
{
    if (!s_pstThreadAsyncObject)
    {
        return (osMessageQueueId_t)NULL;
    }

    if (!s_pstThreadAsyncObject->pfOSMessageQueueNew)
    {
        return (osMessageQueueId_t)NULL;
    }

    return s_pstThreadAsyncObject->pfOSMessageQueueNew(msg_count, msg_size, attr);
}

/// Get name of a Message Queue object.
/// \param[in]     mq_id         message queue ID obtained by \ref osMessageQueueNew.
/// \return name as null-terminated string.
const char *osMessageQueueGetName (osMessageQueueId_t mq_id)
{
    if (!s_pstThreadAsyncObject)
    {
        return "no define";
    }

    if (!s_pstThreadAsyncObject->pfOSMessageQueueGetName)
    {
        return "unknow";
    }

    return s_pstThreadAsyncObject->pfOSMessageQueueGetName(mq_id);
}

/// Put a Message into a Queue or timeout if Queue is full.
/// \param[in]     mq_id         message queue ID obtained by \ref osMessageQueueNew.
/// \param[in]     msg_ptr       pointer to buffer with message to put into a queue.
/// \param[in]     msg_prio      message priority.
/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout)
{
    if (!s_pstThreadAsyncObject)
    {
        return osError;
    }

    if (!s_pstThreadAsyncObject->pfOSMessageQueuePut)
    {
        return osOK;
    }

    return s_pstThreadAsyncObject->pfOSMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout);
}

/// Get a Message from a Queue or timeout if Queue is empty.
/// \param[in]     mq_id         message queue ID obtained by \ref osMessageQueueNew.
/// \param[out]    msg_ptr       pointer to buffer for message to get from a queue.
/// \param[out]    msg_prio      pointer to buffer for message priority or NULL.
/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout)
{
    return osOK;
}

/// Get maximum number of messages in a Message Queue.
/// \param[in]     mq_id         message queue ID obtained by \ref osMessageQueueNew.
/// \return maximum number of messages.
uint32_t osMessageQueueGetCapacity (osMessageQueueId_t mq_id)
{
    if (!s_pstThreadAsyncObject)
    {
        return 0;
    }

    if (!s_pstThreadAsyncObject->pfOSMessageQueueGetCapacity)
    {
        return 0;
    }

    return s_pstThreadAsyncObject->pfOSMessageQueueGetCapacity(mq_id);
}

/// Get maximum message size in a Memory Pool.
/// \param[in]     mq_id         message queue ID obtained by \ref osMessageQueueNew.
/// \return maximum message size in bytes.
uint32_t osMessageQueueGetMsgSize (osMessageQueueId_t mq_id)
{
    if (!s_pstThreadAsyncObject)
    {
        return 0;
    }

    if (!s_pstThreadAsyncObject->pfOSMessageQueueGetMsgSize)
    {
        return 0;
    }

    return s_pstThreadAsyncObject->pfOSMessageQueueGetMsgSize(mq_id);
}

/// Get number of queued messages in a Message Queue.
/// \param[in]     mq_id         message queue ID obtained by \ref osMessageQueueNew.
/// \return number of queued messages.
uint32_t osMessageQueueGetCount (osMessageQueueId_t mq_id)
{
    if (!s_pstThreadAsyncObject)
    {
        return 0;
    }

    if (!s_pstThreadAsyncObject->pfOSMessageQueueGetCount)
    {
        return 0;
    }

    return s_pstThreadAsyncObject->pfOSMessageQueueGetCount(mq_id);
}

/// Get number of available slots for messages in a Message Queue.
/// \param[in]     mq_id         message queue ID obtained by \ref osMessageQueueNew.
/// \return number of available slots for messages.
uint32_t osMessageQueueGetSpace (osMessageQueueId_t mq_id)
{
    if (!s_pstThreadAsyncObject)
    {
        return 0;
    }

    if (!s_pstThreadAsyncObject->pfOSMessageQueueGetSpace)
    {
        return 0;
    }

    return s_pstThreadAsyncObject->pfOSMessageQueueGetSpace(mq_id);
}

/// Reset a Message Queue to initial empty state.
/// \param[in]     mq_id         message queue ID obtained by \ref osMessageQueueNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMessageQueueReset (osMessageQueueId_t mq_id)
{
    if (!s_pstThreadAsyncObject)
    {
        return osError;
    }

    if (!s_pstThreadAsyncObject->pfOSMessageQueueReset)
    {
        return osOK;
    }

    return s_pstThreadAsyncObject->pfOSMessageQueueReset(mq_id);
}

/// Delete a Message Queue object.
/// \param[in]     mq_id         message queue ID obtained by \ref osMessageQueueNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id)
{
    if (!s_pstThreadAsyncObject)
    {
        return osError;
    }

    if (!s_pstThreadAsyncObject->pfOSMessageQueueDelete)
    {
        return osOK;
    }

    return s_pstThreadAsyncObject->pfOSMessageQueueDelete(mq_id);
}

